//
//  @ Project : Galaxy Star Trading System
//  @ File Name : BarData.cpp
//  @ Date : 2014/9/5
//  @ Author :
//
//

#include "../StdInc.h"
#include <boost/format.hpp>
using namespace boost;

namespace GSTrader
{
	namespace TradeBase
	{
		CBarData::CBarData() : m_dOpen(0), m_dHigh(0), m_dLow(0), m_dClose(0), m_dOpenInterest(0), m_dVolume(0), m_dAmount(0), m_nStatus(0),
			m_nInstrumentID(-1), m_nType(0), m_nCapacity(0), m_nCount(0)
		{
			m_nBeginVolume = 0;
			m_dBeginAmount = 0;
			m_dTotalVolume = 0;
			m_dTotalAmount = 0;
		}

		CBarData::CBarData(CBarData* pBar)
		{
			m_nInstrumentID = pBar->m_nInstrumentID;
			m_dOpen		= pBar->m_dOpen;
			m_dHigh		= pBar->m_dHigh;
			m_dLow		= pBar->m_dLow;
			m_dClose	= pBar->m_dClose;
			m_dOpenInterest = pBar->m_dOpenInterest;
			m_dVolume	= pBar->m_dVolume;
			m_dAmount	= pBar->m_dAmount;
			m_DateTime	= pBar->m_DateTime;
			m_OpenTime	= pBar->m_OpenTime;
			m_CloseTime = pBar->m_CloseTime;
			m_nStatus	= pBar->m_nStatus;
			m_nType		= pBar->m_nType;
			m_nCapacity = pBar->m_nCapacity;
			m_nCount	= pBar->m_nCount;
			m_nBeginVolume = pBar->m_nBeginVolume;
			m_dBeginAmount = pBar->m_dBeginAmount;
			m_dTotalVolume = pBar->m_dTotalVolume;
			m_dTotalAmount = pBar->m_dTotalAmount;
		}

		CBarData::CBarData(int nInstrumentID, int nBarType, int nBarCycle) : CBarData()
		{
			m_nInstrumentID = nInstrumentID;
			m_nType			= nBarType;
			m_nCapacity		= nBarCycle;
		}

		CBarData::~CBarData()
		{

		}

		CBarData& CBarData::operator = (const SHistoricalData& r)
		{
			this->SetDateTime(r.m_tTime);
			m_dOpen		= r.m_dOpen;
			m_dHigh		= r.m_dHigh;
			m_dLow		= r.m_dLow;
			m_dClose	= r.m_dClose;
			m_dOpenInterest = r.m_dOpenInterest;
			m_dVolume	= r.m_dVolume;
			m_dAmount	= r.m_dAmount;
			return *this;
		}

		bool CBarData::operator == (const SHistoricalData& r)
		{
			if ((this->GetTimeT() == r.m_tTime) &&
			    (this->m_dOpen == r.m_dOpen) &&
			    (this->m_dHigh == r.m_dHigh) &&
			    (this->m_dLow == r.m_dLow) &&
			    (this->m_dClose == r.m_dClose) &&
			    (this->m_dVolume == r.m_dVolume) &&
			    (this->m_dAmount == r.m_dAmount) &&
			    (this->m_dOpenInterest == r.m_dOpenInterest))
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		time_t CBarData::GetTimeT()
		{
			return (int)this->m_DateTime.GetTime_t();
		}

		CTimePoint CBarData::GetDataTime()
		{
			return this->m_DateTime;
		}

		void CBarData::SetDateTime(CTimePoint ParDateTime)
		{
			this->m_DateTime = ParDateTime;
		}

		double CBarData::GetValueByType(int bardata)
		{
			switch (bardata)
			{
				case bdtClose:
				{
					return m_dClose;
				}
				case bdtOpen:
				{
					return m_dOpen;
				}
				case bdtHigh:
				{
					return m_dHigh;
				}
				case bdtLow:
				{
					return m_dLow;
				}
				case bdtMedian:
				{
					return (m_dHigh + m_dLow) / 2.0;
				}
				case bdtTypical:
				{
					return (m_dHigh + m_dLow + m_dClose) / 3.0;
				}
				case bdtAverage:
				{
					return Average();
				}
				case bdtVolume:
				{
					return m_dVolume;
				}
				case bdtOpenInt:
				{
					return m_dOpenInterest;
				}
				default:
				{
					return GenerateNaN();
				}
			}
		}

		double CBarData::Average()
		{
			return (m_dOpen + m_dHigh + m_dClose + m_dLow) / 4.0;
		}

		string CBarData::ToString()
		{
			format fmt(g_language == slChinese ? Chinese::c_szFmt3 : English::c_szFmt3);
			fmt % m_nInstrumentID;
			fmt % m_dOpen;
			fmt % m_dHigh;
			fmt % m_dLow;
			fmt % m_dClose;
			fmt % m_OpenTime.ToString();
			fmt % m_CloseTime.ToString();
			fmt % m_dVolume;
			fmt % m_dAmount;
			return fmt.str();
		}

		void CBarData::UpdateData(CDepthMarketData* pData)
		{
			assert(pData != NULL);
			assert(m_nInstrumentID == pData->m_nInstrumentID);

			if (pData->m_dPrice > m_dHigh)
			{
				m_dHigh = pData->m_dPrice;
			}

			if (pData->m_dPrice < m_dLow)
			{
				m_dLow = pData->m_dPrice;
			}

			m_dClose	= pData->m_dPrice;
			m_CloseTime = pData->GetTimePoint();

			m_dTotalVolume = pData->m_nVolume;
			m_dTotalAmount = pData->m_dAmount;

			m_dVolume = pData->m_nVolume - m_nBeginVolume;
			m_dAmount = pData->m_dAmount - m_dBeginAmount;

			m_nStatus = baUpdate;
			m_nCount++;
		}

		void CBarData::SetData(CDepthMarketData* pData)
		{
			assert(pData != NULL);
			assert(m_nInstrumentID == pData->m_nInstrumentID);

			m_dOpen  = pData->m_dPrice;
			m_dHigh  = pData->m_dPrice;
			m_dLow   = pData->m_dPrice;
			m_dClose = pData->m_dPrice;

			m_dOpenInterest = pData->m_dOpenInterest;
			m_nBeginVolume = pData->m_nVolume;
			m_dBeginAmount = pData->m_dAmount;
			m_dTotalVolume = pData->m_nVolume;
			m_dTotalAmount = pData->m_dAmount;

			m_dVolume = 0;
			m_dAmount = 0;
			m_OpenTime = GetBarOpenTime(pData);
			m_CloseTime = pData->GetTimePoint();
			m_nStatus = baOpen;
			m_nCount++;
		}

		CTimePoint CBarData::GetBarOpenTime(CDepthMarketData* pData)
		{
			CTimePoint tOpenTime = pData->GetTimePoint();
			if (m_nType == barTime && m_nCapacity > 0)
			{
				int nBarSize = m_nCapacity ;
				CTimePoint tmBegin = CTimePoint::GetTimeBeginDay(tOpenTime);
				int nSecond = ((tOpenTime - tmBegin) / nBarSize) * (nBarSize);

				tOpenTime = tmBegin;
				tOpenTime.AddSecond(nSecond);
			}

			return tOpenTime;
		}

		CTimePoint CBarData::GetBarCloseTime(CDepthMarketData* pData)
		{
			CTimePoint tCloseTime ;
			if (m_nType == barTime)
			{
				tCloseTime = GetBarOpenTime(pData);
				tCloseTime.AddSecond(m_nCapacity);
			}
			else
			{
				tCloseTime = pData->GetTimePoint();
			}

			return tCloseTime;
		}
	}
}